package xyz.chaobei.mall.security.component;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import xyz.chaobei.mall.security.config.JwtConfig;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @copyright (C), 2015-2020
 * @fileName: DefaultTokenServer
 * @author: MRC
 * @date: 2020/10/21 0:02
 * @description: 默认生成token 和校验token 的组件
 */
@Component
@Slf4j
public class DefaultTokenServer {

    private final String PAY_LOAD_SUB_KEY = "sub";

    private final String PAY_LOAD_ISS_KEY = "iss";
    private final String PAY_LOAD_ISS_VALUE = "mall-pro";
    private final String PAY_LOAD_IAT_KEY = "iat";

    @Autowired
    private JwtConfig jwtConfig;

    /**
     * <p>生成token/通过用户基本信息
     * <p>author: <a href='mailto:maruichao52@gmail.com'>MRC</a>
     *
     * @param userDetails
     * @return java.lang.String
     * @since 2020/10/21
     **/
    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();

        claims.put(PAY_LOAD_SUB_KEY, userDetails.getUsername());
        claims.put(PAY_LOAD_IAT_KEY, new Date());
        claims.put(PAY_LOAD_ISS_KEY, PAY_LOAD_ISS_VALUE);

        return buildToken(claims);
    }

    /**
     * 功能描述: 通过负载生成token
     *
     * @Param: claims 负载
     * @Return: java.lang.String
     * @Author: MRC
     * @Date: 2020/10/21 0:17
     */
    private String buildToken(Map<String, Object> claims) {
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(generateExpirationDate())
                .signWith(SignatureAlgorithm.HS512, jwtConfig.getSecret())
                .compact();
    }

    /**
     * 功能描述: 通过自定义过期秒数、计算过期时间
     *
     * @Return: java.util.Date
     * @Author: MRC
     * @Date: 2020/10/21 0:18
     */
    private Date generateExpirationDate() {
        return new Date(System.currentTimeMillis() + jwtConfig.getExpiration() * 1000);
    }

    /**
     * <p>从toKen中获取负载信息
     * <p>author: <a href='mailto:maruichao52@gmail.com'>MRC</a>
     *
     * @param token 获取的token
     * @return io.jsonwebtoken.Claims
     * @since 2020/10/22
     **/
    private Claims getClaimsFromToken(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(jwtConfig.getSecret())
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            log.info("JWT格式验证失败:{}", token);
        }
        return claims;
    }

    /**
     * <p>首先获取token当中的负载、而后从负载中取出sub
     * <p>author: <a href='mailto:maruichao52@gmail.com'>MRC</a>
     *
     * @param token 被校验的token
     * @return java.lang.String
     * @since 2020/10/22
     **/
    public String getUserNameFromToken(String token) {
        String username;
        try {
            Claims claims = getClaimsFromToken(token);
            username = claims.getSubject();
        } catch (Exception e) {
            username = null;
        }
        return username;
    }

    /**
     * <p>当前token 是否过期、若过期返回true
     * <p>author: <a href='mailto:maruichao52@gmail.com'>MRC</a>
     *
     * @param token 当前token
     * @return boolean
     * @since 2020/10/22
     **/
    public boolean isTokenExpired(String token) {
        Date expiredDate = getExpiredDateFromToken(token);
        return expiredDate.before(new Date());
    }
    /**
     * <p>从负载中获取过期时间
     * <p>author: <a href='mailto:maruichao52@gmail.com'>MRC</a>
     *
     * @param token
     * @return java.util.Date
     * @since 2020/10/22
     **/
    private Date getExpiredDateFromToken(String token) {
        Claims claims = getClaimsFromToken(token);
        return claims.getExpiration();
    }


}
